home *** CD-ROM | disk | FTP | other *** search
- ;* CARCDR.ASM
- ;************************************************************************
- ;* *
- ;* PC Scheme/Geneva 4.00 Borland TASM code *
- ;* *
- ;* (c) 1985-1988 by Texas Instruments, Inc. See COPYRIGHT.TXT *
- ;* (c) 1992 by L. Bartholdi & M. Vuilleumier, University of Geneva *
- ;* *
- ;*----------------------------------------------------------------------*
- ;* *
- ;* c[ad]+r Support (interpreter support) *
- ;* *
- ;*----------------------------------------------------------------------*
- ;* *
- ;* Created by: John Jensen Date: 1985 *
- ;* Revision history: *
- ;* - 26 Feb 86: Modified the "CONS" support to attempt a "short circuit"*
- ;* allocation of a list cell, instead of calling the *
- ;* "alloc_list_cell" support unconditionally. (JCJ) *
- ;* - 18 Jun 92: Renaissance (Borland Compilers, ...) *
- ;* *
- ;* ``In nomine omnipotentii dei'' *
- ;************************************************************************
- IDEAL
- %PAGESIZE 60, 132
- MODEL small
- LOCALS @@
-
- INCLUDE "scheme.ash"
- INCLUDE "interprt.ash"
-
- ; load arguments for c?r
- MACRO load_arg
- get2op ; fetch source/destination register numbers
- save <si> ; save the location pointer
- mov bl, ah ; copy the source register number
- mov si, [regs+bx.disp] ; load contents of the source register
- mov bl, [regs+bx.bpage]
- ENDM
-
- DATASEG
-
- m_car DB "CAR", 0
- m_cdr DB "CDR", 0
- m_caar DB "CAAR", 0
- m_cadr DB "CADR", 0
- m_cdar DB "CDAR", 0
- m_cddr DB "CDDR", 0
- m_caaar DB "CAAAR", 0
- m_caadr DB "CAADR", 0
- m_cadar DB "CADAR", 0
- m_caddr DB "CADDR", 0
- m_cdaar DB "CDAAR", 0
- m_cdadr DB "CDADR", 0
- m_cddar DB "CDDAR", 0
- m_cdddr DB "CDDDR", 0
- m_cadddr DB "CADDDR", 0
-
- m_table DW m_car, m_cdr
- DW m_caar, m_cadr, m_cdar, m_cddr
- DW m_caaar, m_caadr , m_cadar, m_caddr
- DW m_cdaar, m_cdadr, m_cddar, m_cdddr
- DW m_cadddr
-
- CODESEG
-
- ;************************************************************************
- ;* %car %CAR DEST *
- ;* *
- ;* Purpose: To obtain the first element of a list. This support is *
- ;* similar to the usual "car" operation except that %car *
- ;* returns #!unassigned if one tries to take the car of *
- ;* nil. *
- ;************************************************************************
- PROC ld_car1
- get1op
- save <si>
- mov bx, ax ; copy operand register number to bx
- mov si, [regs+bx.disp] ; load the source operand
- mov bl, [regs+bx.bpage]
- cmp [ptype+bx], LISTTYPE
- jne @@error
- cmp bl, 0 ; is source operand nil?
- jne $$endcar
- $$undefined:
- mov bx, ax ; reload dest register number
- mov [regs+bx.bpage], UN_PAGE*2 ; set destination reg
- mov [regs+bx.disp], UN_DISP ; to #!unassigned
- jmp next_pc
- @@error:
- DATASEG
- @@msg DB "%CAR", 0
- CODESEG
- lea ax, [@@msg]
- jmp bad_one
- ENDP ld_car1
-
- ;************************************************************************
- ;* %cdr %CDR DEST *
- ;* *
- ;* Purpose: To obtain the rest of a list. This support is similar *
- ;* to the usual "cdr" operation except that %cdr returns *
- ;* #!unassigned if one tries to take the cdr of nil. *
- ;************************************************************************
- PROC ld_cdr1
- get1op
- save <si>
- mov bx, ax ; copy operand register number to bx
- mov si, [regs+bx.disp] ; load the source operand
- mov bl, [regs+bx.bpage]
- cmp bl, 0 ; is source operand nil?
- je $$undefined
- cmp [ptype+bx], LISTTYPE
- je $$endcdr
- DATASEG
- @@msg DB "%CDR", 0
- CODESEG
- lea ax, [@@msg]
- jmp bad_one
- ENDP ld_cdr1
-
- ;************************************************************************
- ;* al ah *
- ;* Take "car" of a list cell LD_CAR dest,src *
- ;************************************************************************
- PROC ld_car
- load_arg
- ; jmp $$endcar
- ENDP
- PROC $$endcar
- cmp [ptype+bx], LISTTYPE
- jne bad_car
- ldpage es, bx
- mov bl, al ; copy destination register number
- mov al, [(LISTDEF es:si).car.page]
- mov [regs+bx.bpage], al
- mov ax, [(LISTDEF es:si).car.disp]
- mov [regs+bx.disp], ax
- jmp next_pc
- ENDP $$endcar
-
- ;************************************************************************
- ;* al ah *
- ;* Take "cdr" of a list cell LD_CDR dest,src *
- ;************************************************************************
- PROC ld_cdr
- load_arg
- ; jmp $$endcdr
- ENDP
- PROC $$endcdr
- cmp [ptype+bx], LISTTYPE
- jne bad_cdr
- ldpage es, bx
- mov bl, al ; copy destination register number
- mov al, [(LISTDEF es:si).cdr.page]
- mov [regs+bx.bpage], al
- mov ax, [(LISTDEF es:si).cdr.disp]
- mov [regs+bx.disp], ax
- jmp next_pc
- ENDP $$endcdr
-
- ;************************************************************************
- ;* error handlers *
- ;************************************************************************
- PROC bad_car ; attempt to take "car"
- ; jmp bad_car
- ENDP
- PROC bad_cdr ; attempt to take "cdr" of non-list cell
- mov si, [save_si] ; load next instruction's address
- mov bx, [cb_reg.page]
- ldpage es, bx
- xor bx, bx ; load opcode of failing instruction
- mov bl, [es:si-3]
- shl bx, 1
- mov ax, [m_table+bx-80h] ; these instructions start at 40h
- ; jmp bad_one
- ENDP
- PROC bad_one
- mov si, [save_si] ; load next instruction's address
- mov bx, [cb_reg.page]
- ldpage es, bx
- xor bx, bx
- mov bl, [es:si-1] ; load register used as last operand
- add bx, OFFSET regs
- push es ; save es over C call
- mov cx, 1
- call set_src_error C, ax, cx, bx
- pop es
- jmp sch_err
- ENDP bad_one
-
- ;************************************************************************
- ;* Simple procedure to put the car, cdr of bl:si in bl:si *
- ;************************************************************************
- PROC $$getcar NEAR
- cmp [ptype+bx], LISTTYPE
- jne bad_car
- ldpage es, bx
- mov bl, [(LISTDEF es:si).car.page]
- mov si, [(LISTDEF es:si).car.disp]
- ret
- ENDP
-
- PROC $$getcdr NEAR
- cmp [ptype+bx], LISTTYPE
- jne bad_cdr
- ldpage es, bx
- mov bl, [(LISTDEF es:si).cdr.page]
- mov si, [(LISTDEF es:si).cdr.disp]
- ret
- ENDP
-
- ;************************************************************************
- ;* al ah *
- ;* Take "cadddr" of a list cell LD_CADDDR dest,src *
- ;************************************************************************
- PROC ld_caddd
- load_arg
- call $$getcdr
- call $$getcdr
- call $$getcdr
- jmp $$endcar
- ENDP
-
- ;************************************************************************
- ;* al ah *
- ;* Take "caar" of a list cell LD_CAAR dest,src *
- ;************************************************************************
- PROC ld_caar
- load_arg
- call $$getcar
- jmp $$endcar
- ENDP
-
- ;************************************************************************
- ;* al ah *
- ;* Take "cadr" of a list cell LD_CADR dest,src *
- ;************************************************************************
- PROC ld_cadr
- load_arg
- call $$getcdr
- jmp $$endcar
- ENDP
-
- ;************************************************************************
- ;* al ah *
- ;* Take "cdar" of a list cell LD_CDAR dest,src *
- ;************************************************************************
- PROC ld_cdar
- load_arg
- call $$getcar
- jmp $$endcdr
- ENDP
-
- ;************************************************************************
- ;* al ah *
- ;* Take "cddr" of a list cell LD_CDDR dest,src *
- ;************************************************************************
- PROC ld_cddr
- load_arg
- call $$getcdr
- jmp $$endcdr
- ENDP
-
- ;************************************************************************
- ;* al ah *
- ;* Take "caaar" of a list cell LD_CAAAR dest,src *
- ;************************************************************************
- PROC ld_caaar
- load_arg
- call $$getcar
- call $$getcar
- jmp $$endcar
- ENDP
-
- ;************************************************************************
- ;* al ah *
- ;* Take "caadr" of a list cell LD_CAADR dest,src *
- ;************************************************************************
- PROC ld_caadr
- load_arg
- call $$getcdr
- call $$getcar
- jmp $$endcar
- ENDP
-
- ;************************************************************************
- ;* al ah *
- ;* Take "cadar" of a list cell LD_CADAR dest,src *
- ;************************************************************************
- PROC ld_cadar
- load_arg
- call $$getcar
- call $$getcdr
- jmp $$endcar
- ENDP
-
- ;************************************************************************
- ;* al ah *
- ;* Take "caddr" of a list cell LD_CADDR dest,src *
- ;************************************************************************
- PROC ld_caddr
- load_arg
- call $$getcdr
- call $$getcdr
- jmp $$endcar
- ENDP
-
- ;************************************************************************
- ;* al ah *
- ;* Take "cdaar" of a list cell LD_CDAAR dest,src *
- ;************************************************************************
- PROC ld_cdaar
- load_arg
- call $$getcar
- call $$getcar
- jmp $$endcdr
- ENDP
-
- ;************************************************************************
- ;* al ah *
- ;* Take "cdadr" of a list cell LD_CDADR dest,src *
- ;************************************************************************
- PROC ld_cdadr
- load_arg
- call $$getcdr
- call $$getcar
- jmp $$endcdr
- ENDP
-
- ;************************************************************************
- ;* al ah *
- ;* Take "cddar" of a list cell LD_CDDAR dest,src *
- ;************************************************************************
- PROC ld_cddar
- load_arg
- call $$getcar
- call $$getcdr
- jmp $$endcdr
- ENDP
-
- ;************************************************************************
- ;* al ah *
- ;* Take "cdddr" of a list cell LD_CDDDR dest,src *
- ;************************************************************************
- PROC ld_cdddr
- load_arg
- call $$getcdr
- call $$getcdr
- jmp $$endcdr
- ENDP
-
- ;************************************************************************
- ;* Macro support for set-car!/set-cdr! *
- ;************************************************************************
- MACRO set_cc field
- LOCAL @@error
- get2op
- save <si>
- mov bl, al
- mov di, [regs+bx.page] ; load dest register page number
- or di, di ; are we trying to set car/cdr of nil?
- jz @@error
- cmp [ptype+di], LISTTYPE
- jne @@error
- ldpage es, di
- mov di, [regs+bx.disp] ; Load destination displacement
- mov bl, ah ; Copy src register number
- mov al, [regs+bx.bpage] ; redefine field's page number
- mov [(LISTDEF es:di).field.page], al
- mov ax, [regs+bx.disp] ; redefine field's displacement
- mov [(LISTDEF es:di).field.disp], ax
- jmp next_pc
- @@error:
- ENDM
-
- ;************************************************************************
- ;* al ah *
- ;* Side effect car field (set-car! dest src) SET-CAR! dest,src *
- ;* *
- ;* Purpose: Interpreter support for the set-car! operation. *
- ;************************************************************************
- PROC set_car
- set_cc car
- DATASEG
- @@msg DB "SET-CAR!", 0
- CODESEG
- lea bx, [@@msg]
- bad_set_car:
- mov ax, [cb_reg.page]
- ldpage es, ax
- $$set_error:
- xor ax, ax
- mov al, [es:si-1]
- add ax, OFFSET regs
- push ax
- xor ax, ax
- mov al, [es:si-2]
- add ax, OFFSET regs
- mov cx, 2
- call set_src_error C, bx, cx, ax
- restore <si>
- jmp sch_err
- ENDP
-
- ;************************************************************************
- ;* al ah *
- ;* Side effect cdr field (set-cdr! dest src) SET-CDR! dest,src *
- ;* *
- ;* Purpose: Interpreter support for the set-cdr! operation. *
- ;************************************************************************
- PROC set_cdr
- set_cc cdr
- DATASEG
- @@msg DB "SET-CDR!", 0
- CODESEG
- lea bx, [@@msg]
- jmp bad_set_car
- ENDP
-
- ;************************************************************************
- ;* dl dh al *
- ;* Cons - Create and define new list cell CONS dest,car,cdr *
- ;* *
- ;* Purpose: Interpreter support for the Scheme "cons" operation. *
- ;************************************************************************
- PROC s_cons
- get2op
- mov dx, ax
- xor ax, ax
- get1op ; load cdr register number
- save <si>
- ; Attempt a "short circuit" list cell allocation
- mov di, [listpage]
- shl di, 1
- mov si, [nextcell+di]
- cmp si, END_LIST
- je @@outofspace
- ldpage es, di
- mov cx, [(LISTDEF es:si).car.disp]
- mov [nextcell+di], cx
- @@resume: ; Move contents of CDR register to CDR field of new list cell
- mov bx, ax ; copy register number to bx
- mov al, [regs+bx.bpage]
- mov [(LISTDEF es:si).cdr.page], al
- mov ax, [regs+bx.disp]
- mov [(LISTDEF es:si).cdr.disp], ax
- mov bl, dh ; Move contents of CAR register to CAR field of new list cell
- mov al, [regs+bx.bpage]
- mov [(LISTDEF es:si).car.page], al
- mov ax, [regs+bx.disp]
- mov [(LISTDEF es:si).car.disp], ax
- mov bl, dl ; Update destination register number with pointer to new list cell
- mov [regs+bx.page], di
- mov [regs+bx.disp], si
- jmp next_pc
-
- @@outofspace:
- push ax dx es
- call alloc_list_cell C, [tmp_adr]
- pop es dx ax
- mov di, [tmp_reg.page]
- mov si, [tmp_reg.disp]
- ldpage es, di
- jmp @@resume
- ENDP s_cons
-
- ;************************************************************************
- ;* List - Create and define new list cell w/ nil cdr LIST dest *
- ;* *
- ;* Purpose: Interpreter support for the Scheme "list" operation. *
- ;************************************************************************
- PROC s_list
- get1op
- lea bx, [tmp_reg]
- save <si>
- push ax ; save register pointer
- call alloc_list_cell C, bx
- pop si ; restore destination register pointer
- mov bx, [tmp_reg.page]
- ldpage es, bx
- mov di, [tmp_reg.disp]
- mov ax, di
- xchg ax, [regs+si.disp]
- xchg bl, [regs+si.bpage] ; put our new pointer, reading the car
- mov [(LISTDEF es:di).car.disp], ax
- mov [(LISTDEF es:di).car.page], bl
- xor ax, ax ; create nil cdr field
- mov [(LISTDEF es:di).cdr.disp], ax
- mov [(LISTDEF es:di).cdr.page], al
- jmp next_pc
- ENDP s_list
-
- ;************************************************************************
- ;* al ah *
- ;* (list a b) LIST2 dest,src *
- ;* *
- ;* Purpose: Interpreter support for the (list a b) operation. *
- ;* *
- ;* Description: This operation: (list a b) *
- ;* is equivalent to: (cons a (cons b nil)) *
- ;************************************************************************
- PROC list2
- get2op
- save <si>
- mov bl, al ; save the destination register number
- push bx
- mov bl, ah ; copy the source register number
- add bx, OFFSET regs
- lea ax, [nil_reg]
- lea cx, [tmp_reg]
- push cx ; save it for later use
- call cons C, cx, bx, ax ; (cons tmp_reg src nil_reg)
- pop cx bx ; restore tmp_reg address
- add bx, OFFSET regs
- call cons C, bx, bx, cx ; (cons dest dest tmp_reg)
- jmp next_pc
- ENDP list2
-
- ;************************************************************************
- ;* (append! list obj) append! dest src *
- ;* *
- ;* Purpose: Scheme interpreter support for the append! primitive *
- ;************************************************************************
- PROC appendb
- get2op
- save <si>
- mov bl, al
- lea di, [regs+bx]
- mov bx, [(REG di).page] ; load list header from dest reg
- cmp [ptype+bx], LISTTYPE
- jne @@error
- cmp bl, NIL_PAGE*2 ; is arg1 == nil?
- jne @@findend
- mov bl, ah ; get 2nd arg & return it in dest reg
- lea si, [regs+bx] ; si=address of src reg
- mov bx, [(REG si).page] ; return source
- mov [(REG di).page], bx
- mov bx, [(REG si).disp]
- mov [(REG di).disp], bx
- jmp next_pc
-
- @@findend:
- mov di, [(REG di).disp]
- @@nextcell:
- ldpage es, bx
- mov bl, [(LISTDEF es:di).cdr.page]
- cmp bl, NIL_PAGE*2 ; CDR == nil?
- je @@endoflist
- cmp [ptype+bx], LISTTYPE ; still pointing to cons nodes?
- jne @@endoflist
- mov di, [(LISTDEF es:di).cdr.disp]
- cmp [s_break], 0
- je @@nextcell
- mov ax, 3
- call restart C, ax ; link to Scheme debugger
-
- @@endoflist:
- mov bl, ah ; else get 2nd arg & return it in dest reg
- lea si, [regs+bx] ; si=address of src reg
- mov bx, [(REG si).page]
- mov [(LISTDEF es:di).cdr.page], bl
- mov bx, [(REG si).disp]
- mov [(LISTDEF es:di).cdr.disp], bx
- jmp next_pc
-
- @@error:
- DATASEG
- @@msg DB "APPEND!", 0
- CODESEG
- lea bx, [@@msg]
- jmp $$set_error
- ENDP appendb
-
- ;************************************************************************
- ;* (list_tail list count) l_tail list(dest) count *
- ;* *
- ;* Purpose: Scheme interpreter support for the list_tail primitive *
- ;************************************************************************
- PROC l_tail
- get2op
- save <si>
-
- xor bh, bh
- mov bl, al
- lea si, [regs+bx] ; saves reg in si for later
-
- xor bh, bh
- mov bl, ah
- add bx, OFFSET regs ; get register containing count
- call int2long C, bx
- or dx, dx
- js @@error
- mov cx, ax ; count is in cx:dx
-
- mov bx, [(REG si).page]
- cmp [ptype+bx], LISTTYPE
- jne @@error
-
- mov ax, bx ; ax <= page of list
- mov bx, [(REG si).disp] ; bx <= disp of list
- @@loop:
- mov di, cx ; get a copy of counter
- or di, dx ; jump if counter is 0
- jz @@ret
- cmp ax, NIL_PAGE * 2 ; end of list?
- je @@ret
- ldpage es, ax
- mov al, [(LISTDEF es:bx).cdr.page]
- mov bx, [(LISTDEF es:bx).cdr.disp]
- sub cx, 1 ; decrement count
- sbb dx, 0
- jmp @@loop
-
- @@ret:
- mov [(REG si).bpage], al ; save page in reg
- mov [(REG si).disp], bx ; save disp in reg
- @@exit:
- jmp next_pc
-
- @@error:
- restore <si>
- xor ax, ax
- mov al, [es:si-1]
- add ax, OFFSET regs ; get last operand
- push ax ; and push for call
- xor ax, ax
- mov al, [es:si-2]
- add ax, OFFSET regs ; get first operand
- push ax ; and push for call
- DATASEG
- @@msg DB "LIST_TAIL", 0
- CODESEG
- lea bx, [@@msg]
- mov ax, 2
- call set_src_error C, bx, ax
- jmp sch_err
- ENDP l_tail
-
- END